fix(release): refuse to tag unless HEAD is at the remote default tip#553
Merged
Conversation
The release tool tags whatever HEAD points at and pushes the tag, but the downstream "chore: bump" commit it creates afterwards is only committed locally (gitPushTags pushes tags, never the branch). When the tool is re-run while HEAD sits on such a local-only bump commit, the new tag lands on a commit that is not on the remote default branch. That is how store/v0.0.28 ended up pinned to the "chore: bump store/v0.0.27" commit, shipping a store release that predated — and therefore did not contain — a Linux keychain fix that had already merged via PRs. Before creating any tag, fetch and verify HEAD equals the tip of the remote default branch (origin/HEAD, falling back to main); refuse otherwise. The check is skipped in --dry and --skip-git modes since they create no tags. Adds an integration test (temp repo + bare remote) covering the in-sync, local-only-commit, and pushed cases, and documents the release workflow and guard in docs/releasing.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…et origin/HEAD - Subtest 3 now creates a local-only commit and asserts failure before pushing, so the fail -> push -> pass recovery path is exercised even when the subtest runs in isolation. - remoteDefaultBranch logs a diagnostic to stderr when origin/HEAD is unset, so a wrong "main" assumption is visible instead of surfacing as a confusing "couldn't find remote ref" fetch error. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
joe0BAB
approved these changes
Jun 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
store/v0.0.28was tagged on1de02f4— thechore: bump store/v0.0.27commit — which predates the Linux keychain DH fix (#548) that had already merged via PRs. Consumers bumping tov0.0.28therefore did not get the fix, surfacing downstream (sandboxes, docker-auth) as intermittentunexpected end of JSON inputwhen decoding credentials.Root cause is in the release tool:
BumpModuletags the currentHEADand pushes the tag, then creates thechore: bumpcommit.gitPushTagspushes tags only — the bump commit stays local.HEADis sitting on such a local-only bump commit, the new tag lands on a commit that is not on the remote default branch and misses anything merged afterwards.What
git fetchand verifyHEADequals the tip of the remote default branch (origin/HEAD, falling back tomain); refuse otherwise with an actionable error.--dry/--skip-gitmodes (they create no tags).docs/releasing.mddocuments the workflow and the guard.Note
store/v0.0.28is left in place (already on the GOPROXY; deleting would break anyone pinned to it).store/v0.0.29was cut onmainHEAD with the fix and is the version consumers should use.Test plan
go test ./release/...— passesgolangci-lint run -c ../.golangci.yml ./release/...— 0 issues🤖 Generated with Claude Code